#include "Optimization.h"

namespace Compiler
{
	namespace Intermediate
	{
		class VariableCleanupOptimizer : public IntraProcOptimizer
		{
		public:
			virtual ProgramOptimizationResult Optimize(RefPtr<ControlFlowGraph> program) override
			{
				ProgramOptimizationResult rs;
				rs.Program = program;
				Dictionary<Variable*, InstructionNode *> referencedVariables;
				for (auto & node : program->Nodes)
				{
					for (auto instrNode = node->Code.FirstNode(); instrNode; instrNode = instrNode->GetNext())
					{
						auto & instr = instrNode->Value;
						if (instr.LeftOperand.IsVariable())
						{
							referencedVariables[instr.LeftOperand.Var] = instrNode;
						}
						for (auto & op : instr.Operands)
						{
							if (op.IsVariable())
							{
								referencedVariables.AddIfNotExists(op.Var, 0);
							}
						}
					}
				}
				program->VarDefs.Clear();
				List<RefPtr<Variable>> newVars;
				for (auto & var : program->Variables)
				{
					InstructionNode * def;
					if (var->Id < program->ParameterCount)
					{
						newVars.Add(_Move(var));
						program->VarDefs.Add(0);
					}
					else if (referencedVariables.TryGetValue(var.Ptr(), def))
					{
						var->Id = newVars.Count();
						newVars.Add(_Move(var));
						program->VarDefs.Add(def);
					}
					else
						rs.Changed = true;
				}
				program->Variables = _Move(newVars);
				return rs;
			}
		};
		IntraProcOptimizer * CreateVariableCleanupOptimizer()
		{
			return new VariableCleanupOptimizer();
		}
	}
}